package zzf.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Controller;

import java.util.Arrays;

//将切面类中的通知方法动态的添加到目标方法运行的位置切入
@Aspect
@Controller
public class LogUtils {
    /*
    * 告诉spring方法都是什么时候运行
    * @Before           :方法执行之前
    * @After            :方法执行之后
    * @AfterReturning   :方法正常返回
    * @AfterThrowing    :方法排除异常
    * */
    //想在目标方法执行之前,传入切入点
    //切入点表达式的固定写法
    //execution(访问权限符 返回值类型 方法的全名(参数表))
    //切入点表达式中支持通配符 * ,匹配多个字符
    //                       可以匹配任意参数
    //                       只能匹配一层路径
    //                       权限修饰符不能用 * 代替,可以不写权限修饰符,就代表匹配任意修饰符
    //
    //                    .. 匹配任意多个参数,任意类型参数
    //                       匹配任意多层路径

    //最模糊的写法 execution(* *(..)) 匹配任意返回值,任意权限修饰符,任意包下任意类的任意方法,任意个数的返回值,任意类型返回值
    //execution(public int zzf.inter.impl.MyMathCalculator.add(int ,int ))
    @Before("execution(public int zzf.inter.impl.MyMathCalculator.*(int,int))")
    public static void logStart(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName() +" :方法开始执行,参数列表:"+ Arrays.asList(joinPoint.getArgs()));
    }
    //想在目标方法正常返回的时候执行
    @AfterReturning(value = "execution(public int zzf.inter.impl.MyMathCalculator.*(int,int))" ,
            returning = "result"
    )

    /*
    * Spring对通知方法的写法要求不要个,权限修饰符,返回值都不要求
    * 但是方法的参数列表不能乱写
    * 参数表中的每一个参数都需要告诉Spring,这个参数的作用,需要在切入点表达式中写明白
    * */
    public static void logRetun(Object result){
        System.out.println("方法返回,返回值:" + result);
    }
    //想在目标方法结束的时候执行
    @After(value = ("execution(public int zzf.inter.impl.MyMathCalculator.*(int,int))"))
    public static void logEnd(){
        System.out.println("方法执行结束,参数列表:");
    }
    /*
    * 通知方法的执行顺序
    * 正常执行 @before -> @After -> @AfterReturning
    * 异常执行 @before -> @After -> @AfterThrowing
    * */


    /*
    * 4:可以在通知方法运行的时候,拿到目标犯法的详细信息
    *   1:需要为通知方法的参数列表中加一个JoinPoint
    *
    * */
}
